package hasthi.tools.analyze;

import hasthi.common.*;
import hasthi.manager.ExecuteCommandDocument;
import hasthi.manager.ManagementLogMessageDocument;
import hasthi.manager.ExecuteCommandDocument.ExecuteCommand;
import hasthi.manager.ManagementLogMessageDocument.ManagementLogMessage;
import hasthi.manager.gui.ActionPanel;
import hasthi.manager.gui.UIContext;
import hasthi.manager.monitering.EventListener;
import hasthi.manager.monitering.MoniteringAgent;
import hasthi.metamodel.ExternalResourceModel;
import hasthi.metamodel.resource.*;
import hasthi.wsdm.ManagedServiceHandle;
import hasthi.common.constants.HasthiConstants;
import hasthi.common.constants.WSDMConstants;
import hasthi.container.SimpleMessageContext;

import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.xml.namespace.QName;

import org.apache.xmlbeans.XmlObject;

public class SystemTestDriver implements EventListener{
    private static final int READING_COUNT = 5;
    private ExternalResourceModel externalResourceModel;
    private UIContext context = null;
    private SystemEventsParser parser = new SystemEventsParser();
    private FileWriter out;
    
    private int eventCount = 0; 
    private int readingCount = 0; 
    
    public SystemTestDriver() throws HasthiException{
        try {
            Properties properties = new Properties();
            FileInputStream in = new FileInputStream("test/hasthi.properties");
            properties.load(in);
            in.close();
            properties.setProperty(HasthiOptions.BOOTSTRAP_NODE, "tyr12.cs.indiana.edu");
            
            BaseContext baseConfigContext = new BaseContext(properties);
            MoniteringAgent moniteringAgent = new MoniteringAgent(baseConfigContext.getMessageBrokerUrl(),baseConfigContext.getManagementTopic());
            moniteringAgent.addTrigger(this);
            moniteringAgent.startMonitering();
            
            out = new FileWriter("hasthi_event"+System.currentTimeMillis()+".log",true);
            
            Map<String, String> hostName2MngAgnetMap = new HashMap<String, String>();
            context = new UIContext(true,baseConfigContext);
            //context.se
            externalResourceModel = context.getExternalResourceModel();
            ManagedResource[] resources = externalResourceModel.getAllResources();
            
            for (ManagedResource resource : resources) {
                if (resource.getName().endsWith("indiana.edu")) {
                    hostName2MngAgnetMap.put(resource.getQName().getLocalPart(), resource
                            .getManagerAgentURL());
                }
            }
            
                    // ManagedResource[] resources =
                    // externalResourceModel.getAllResources();
//                String ipAddress = new URI(coordinatorAddress).getHost();
//                InetAddress address = InetAddress.getByName(ipAddress);
//                String hostName = address.getCanonicalHostName();
//                String managerAgentURL = hostName2MngAgnetMap.get(hostName);
//                HostAgentBasedHostProxy remoteSystemProxy = new HostAgentBasedHostProxy(
//                        baseContext, managerAgentURL, contianier);
//                remoteSystemProxy.runCommand(address.getCanonicalHostName(),
//                        "/u/hperera/svncode/management/target/dist-bin/mngenode.sh", null,
//                        "/u/hperera/svncode/management/target/dist-bin", false, "Manager Started And Joined Coordination Ring Sucessfully");
//                Thread.sleep(10000);
//                // Create new manager
//                shutDownCoordinator();
   
   // UIContext context = new UIContext(true);
   // // //
   // // ManagementRing ring =
   // ResourceModelFactory.getManagerRingState(context);
   // // int managerCount = ring.getManagerDataArray().length;
   // int resourceCount =
   // context.getExternalResourceModel().getAllResources().length;
            pickAndKillAResource();
        } catch (IOException e) {
            throw new HasthiException(e,HasthiException.FaultCode.LocalError);
        }
    }

    public void write(String str){
        try {
            out.write(str);
            out.write("\n");
            out.flush();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    public String getSearchPath() {
        // TODO Auto-generated method stub
        return null;
    }

    public void performTriggerAction(XmlObject event, XmlObject[] matchingResults)
            throws HasthiException {
      //System.out.println("Event recived "+ event);
        eventCount++;
        try {
            if(event instanceof ManagementLogMessageDocument){
                ManagementLogMessageDocument document = (ManagementLogMessageDocument)event;
                ManagementLogMessage logMessage = document.getManagementLogMessage();
                write(logMessage.getMesssage());
                System.out.println(logMessage.getMesssage());
                if(SystemEventsParser.hasMatch(logMessage.getMesssage(), SystemEventsParser.systemRecoveredPattern) != null){
                    externalResourceModel.reload();
                    readingCount++;
                    if(readingCount > READING_COUNT){
                        parser.printSummery();
                        try{out.close();}catch(Exception e){}
                        System.out.println("Test Completed");
                        System.exit(0);
                    }
                    pickAndKillAResource();
                }
                parser.addEvent(logMessage.getMesssage());
            }
            
            if(eventCount%200 == 0){
                parser.printSummery();
            }
        } catch (InterruptedException e) {
            throw new HasthiException(e,HasthiException.FaultCode.LocalError);
        }
    }
    
    private void pickAndKillAResource() throws HasthiException{
        Thread t = new Thread(new Runnable() {
            public void run() {
                try {
                    Thread.sleep(120000);
                    ManagedResource[] allResources = externalResourceModel.getAllResources();
                    for(ManagedResource resource:allResources ){
                        if("{http://www.extreme.indiana.edu/lead}FactoryService".equals(resource.getType()) &&
                                (resource.getState().equals(WSDMConstants.SystemState.BusyState.toString())
                                    || resource.getState().equals(WSDMConstants.SystemState.SaturatedState.toString())
                                    ||resource.getState().equals(WSDMConstants.SystemState.IdleState.toString()))){
                            ManagedResource host = externalResourceModel.getResource(new QName(((ManagedService)resource).getHost()));
                            ActionPanel.runCommand(context, host.getManagerAgentURL(), 
                                    "/u/drlead/deployment/development/sgfac2/target/dist-bin", 
                                    "processkill:edu.indiana.extreme.gfac.services.FactoryServiceImpl");
                            context.getBaseContext().getDlogger().info("Resource "+resource.getName() + " Stopped");
                            context.getBaseContext().getDlogger().info("System Error Occured(Real time)");
                            return;
                        }
                    }
                    throw new HasthiException("No Resource found for killing",HasthiException.FaultCode.LocalError);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (HasthiException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });
        t.start();
        
    }
    public static void main(String[] args) throws HasthiException {
        SystemTestDriver systemTestDriver = new SystemTestDriver();
    }
    
}
